package com.example.testdemo.controllers;

import org.andengine.engine.camera.Camera;
import org.andengine.engine.camera.hud.controls.DigitalOnScreenControl;
import org.andengine.entity.sprite.ButtonSprite;
import org.andengine.entity.sprite.Sprite;
import org.andengine.entity.text.Text;
import org.andengine.opengl.font.Font;
import org.andengine.opengl.texture.region.ITextureRegion;
import org.andengine.opengl.texture.region.ITiledTextureRegion;
import org.andengine.opengl.vbo.VertexBufferObjectManager;
import org.andengine.util.HorizontalAlign;
import org.andengine.util.color.Color;

import com.example.testdemo.TankGameActivity;
import com.example.testdemo.manager.CamerasManager;
import com.example.testdemo.manager.ResourcesManager;
import com.example.testdemo.resources.CharacterResources;
import com.example.testdemo.utils.Scoreboard;

public class FcController extends DigitalOnScreenControl implements Scoreboard {

	@SuppressWarnings("unused")
	private String TAG = FcController.class.getSimpleName();

	private static final int BUTTON_WIDTH = 83;
	private static final int BUTTON_HEIGHT = 83;

	private TankGameActivity mActivity;
	private CharacterResources mCharacterResources;

	private TextButtonSprite mButtonA = null;
	private TextButtonSprite mButtonB = null;

	// Scoreboard
	private final int PLAYER_MAX_LIVES = 6;
	private int mPlayerLives = 0;
	private int mPlayerKillCount = 0;
	private int mPlayerPoints = 0;
	private Text mHPText = null;
	private ChangeableText mScoreText = null;
	private Sprite mPlayerLifeIcon[] = null;

	public FcController(float pX, float pY, Camera pCamera,
	        ITextureRegion pControlBaseTextureRegion,
	        ITextureRegion pControlKnobTextureRegion,
	        float pTimeBetweenUpdates, TankGameActivity activity,
	        IOnScreenControlListener pOnScreenControlListener) {
		super(pX, pY, pCamera, pControlBaseTextureRegion,
		        pControlKnobTextureRegion, pTimeBetweenUpdates, activity
		                .getVertexBufferObjectManager(),
		        pOnScreenControlListener);

		mActivity = activity;
		mCharacterResources = (CharacterResources) ResourcesManager
		        .getInstance().getResources(
		                ResourcesManager.RESOURCES_CHARACTER);
		final float width = CamerasManager.SCREEN_RESOLUTION.x;
		final float height = CamerasManager.SCREEN_RESOLUTION.y;

		mButtonA = new TextButtonSprite(width - BUTTON_WIDTH * 2, height
		        - BUTTON_HEIGHT, mCharacterResources.mButtonTextureRegion,
		        mCharacterResources.mFont, "A",
		        mActivity.getVertexBufferObjectManager());
		mButtonB = new TextButtonSprite(width - BUTTON_WIDTH, height
		        - BUTTON_HEIGHT, mCharacterResources.mButtonTextureRegion,
		        mCharacterResources.mFont, "B",
		        mActivity.getVertexBufferObjectManager());

		mButtonA.setButtonTextColor(new Color(0.9f, 0.5f, 0.5f));
		mButtonB.setButtonTextColor(new Color(0.5f, 0.5f, 1f));

		attachChild(mButtonA);
		attachChild(mButtonB);
		registerTouchArea(mButtonA);
		registerTouchArea(mButtonB);

		// scoreboard
		initScoreboard(width, height);
	}

	public void setButtonAOnClickListener(ButtonSprite.OnClickListener listener) {
		mButtonA.setOnClickListener(listener);
	}

	public void setButtonBOnClickListener(ButtonSprite.OnClickListener listener) {
		mButtonB.setOnClickListener(listener);
	}

	public void setButtonAPressHoldListener(IOnButtonPressHoldListener listener) {
		mButtonA.setOnButtonPressHoldListener(listener);
	}

	public void setButtonBPressHoldListener(IOnButtonPressHoldListener listener) {
		mButtonB.setOnButtonPressHoldListener(listener);
	}

	public void setButtonsAlpha(float alpha) {
		mButtonA.setAlpha(alpha);
		mButtonB.setAlpha(alpha);
	}

	public TextButtonSprite getButtonA() {
		return mButtonA;
	}

	public TextButtonSprite getButtonB() {
		return mButtonB;
	}

	public void hideController() {
		unregisterTouchArea(getControlBase());
		unregisterTouchArea(getControlKnob());
		unregisterTouchArea(mButtonA);
		unregisterTouchArea(mButtonB);

		getControlBase().setVisible(false);
		getControlKnob().setVisible(false);
		mButtonA.setVisible(false);
		mButtonB.setVisible(false);
	}

	public void showController() {
		registerTouchArea(getControlBase());
		registerTouchArea(getControlKnob());
		registerTouchArea(mButtonA);
		registerTouchArea(mButtonB);

		getControlBase().setVisible(true);
		getControlKnob().setVisible(true);
		mButtonA.setVisible(true);
		mButtonB.setVisible(true);
	}

	// Scoreboard
	private void initScoreboard(float width, float height) {
		mScoreText = new ChangeableText(0, 0, mCharacterResources.mFont, "0",
		        HorizontalAlign.RIGHT, 10000,
		        mActivity.getVertexBufferObjectManager());

		mScoreText.setPosition(width - mScoreText.getWidth(), 0, true);
		mScoreText.setAlpha(0.85f);
		attachChild(mScoreText);

		mHPText = new Text(2, 0, mCharacterResources.mFont, "HP",
		        mActivity.getVertexBufferObjectManager());
		mHPText.setAlpha(0.5f);
		attachChild(mHPText);

		mPlayerLifeIcon = new Sprite[PLAYER_MAX_LIVES];
		float iconX = 2 + mHPText.getWidth();
		for (int i = 0; i < PLAYER_MAX_LIVES; i++) {
			iconX += 2;
			mPlayerLifeIcon[i] = new Sprite(iconX, 0,
			        mCharacterResources.mLifeTextureRegion,
			        mActivity.getVertexBufferObjectManager());
			mPlayerLifeIcon[i].setAlpha(0.5f);
			mPlayerLifeIcon[i].setVisible(false);
			mPlayerLifeIcon[i].setIgnoreUpdate(true);
			attachChild(mPlayerLifeIcon[i]);
			iconX += mPlayerLifeIcon[i].getWidth();
		}
	}

	@Override
	public void addPlayerKill(int kills) {
		mPlayerKillCount += kills;
	}

	@Override
	public int getPlayerKills() {
		return mPlayerKillCount;
	}

	@Override
	public void addPlayerPoint(int points) {
		mPlayerPoints += points;
		mScoreText.setText(String.valueOf(mPlayerPoints));
	}

	@Override
	public int getPlayerPoints() {
		return mPlayerPoints;
	}

	@Override
	public void setPlayerLives(int lives) {
		mPlayerLives = lives;
		for (int i = 0; i < mPlayerLives - 1; i++) {
			mPlayerLifeIcon[i].setVisible(true);
		}
	}

	@Override
	public void addPlayerLife() {
		mPlayerLives++;
		int index = mPlayerLives - 2;
		if (index >= 0) {
			mPlayerLifeIcon[index].setVisible(true);
		}
	}

	@Override
	public void delPlayerLife() {
		mPlayerLives--;
		int index = mPlayerLives - 1;
		if (index >= 0) {
			mPlayerLifeIcon[index].setVisible(false);
		}
	}

	@Override
	public int getPlayerLives() {
		return mPlayerLives;
	}

	public void showWin() {
		hideController();
		Text win = new Text(CamerasManager.SCREEN_RESOLUTION.x / 2,
		        CamerasManager.SCREEN_RESOLUTION.y / 2,
		        mCharacterResources.mFont, "You win !",
		        mActivity.getVertexBufferObjectManager());
		win.setPosition(win.getX() - win.getWidth() / 2,
		        win.getY() - win.getHeight() / 2);
		attachChild(win);
	}

	public void showLose() {
		hideController();
		Text lose = new Text(CamerasManager.SCREEN_RESOLUTION.x / 2,
		        CamerasManager.SCREEN_RESOLUTION.y / 2,
		        mCharacterResources.mFont, "You lose !",
		        mActivity.getVertexBufferObjectManager());
		lose.setPosition(lose.getX() - lose.getWidth() / 2,
		        lose.getY() - lose.getHeight() / 2);
		attachChild(lose);
	}

	public void disposeScoreboard() {
		mPlayerLives = 0;
		mPlayerKillCount = 0;
		mPlayerPoints = 0;

		detachChild(mHPText);
		mHPText.dispose();
		for (Sprite icon : mPlayerLifeIcon) {
			detachChild(icon);
			icon.dispose();
		}

		detachChild(mScoreText);
		mScoreText.dispose();

		mHPText = null;
		mScoreText = null;
		mPlayerLifeIcon = null;
	}

	public void disposeController() {
		mActivity.runOnUpdateThread(new Runnable() {
			@Override
			public void run() {
				disposeScoreboard();
				clearTouchAreas();
				clearUpdateHandlers();
				detachChildren();
				dispose();
			}
		});
	}

	public static class ChangeableText extends Text {
		private HorizontalAlign mAlignment;
		private float mInitialX;

		public ChangeableText(float pX, float pY, Font pFont, String pText,
		        HorizontalAlign pHorizontalAlign, int pCharactersMaximum,
		        VertexBufferObjectManager pVertexBufferObjectManager) {
			super(pX, pY, pFont, pText, pCharactersMaximum,
			        pVertexBufferObjectManager);
			mAlignment = pHorizontalAlign;
			mInitialX = pX;
			alignText();
		}

		public void setPosition(float pX, float pY, boolean updateInitialX) {
			setPosition(pX, pY);
			if (updateInitialX) {
				mInitialX = pX;
				alignText();
			}
		}

		@Override
		public void setText(final CharSequence pText) {
			super.setText(pText);
			alignText();
		}

		private void alignText() {
			float textwidth = getWidth();
			float x = mInitialX;
			if (mAlignment == HorizontalAlign.CENTER)
				x = mInitialX - textwidth / 2;
			if (mAlignment == HorizontalAlign.RIGHT)
				x = mInitialX - textwidth;
			setPosition(x, mY);
		}
	}

	public interface IOnButtonPressHoldListener {
		public void onPressedTrigger();

		public void onPressed();

		public void onPressedDone();
	}

	private static class TextButtonSprite extends ButtonSprite {
		@SuppressWarnings("unused")
		private static final String TAG = TextButtonSprite.class
		        .getSimpleName();

		private Text mText;

		private final int TRIGGER_PRESSED = 500;
		private final int PRESSED_HOLD_UPDATE = 500;
		private IOnButtonPressHoldListener mPressedListener;
		private long mPressedStartTime = 0;
		private long mPressedHoldTime = 0;
		private boolean mIsPressedHoldState = false;

		public TextButtonSprite(final float pX, final float pY,
		        final ITiledTextureRegion pTiledTextureRegion,
		        final Font pFont, final String pText,
		        final VertexBufferObjectManager pVertexBufferObjectManager) {
			super(pX, pY, pTiledTextureRegion, pVertexBufferObjectManager);
			mText = new Text(BUTTON_WIDTH / 2f, BUTTON_HEIGHT / 2f, pFont,
			        pText, pVertexBufferObjectManager);
			mText.setScale(1.3f);
			mText.setPosition(mText.getX() - mText.getWidth() / 2, mText.getY()
			        - mText.getHeight() / 2);
			attachChild(mText);
		}

		public void setButtonTextColor(Color color) {
			mText.setColor(color);
		}

		public void setOnButtonPressHoldListener(
		        IOnButtonPressHoldListener listener) {
			mPressedListener = listener;
		}

		@Override
		public void setAlpha(float pAlpha) {
			super.setAlpha(pAlpha);
			mText.setAlpha(pAlpha + 0.15f);
		}

		@Override
		protected void onManagedUpdate(float pSecondsElapsed) {
			super.onManagedUpdate(pSecondsElapsed);
			if (getState() == State.NORMAL) {
				mPressedStartTime = 0;
				mPressedHoldTime = 0;
				mIsPressedHoldState = false;
			} else if (mIsPressedHoldState) {
				if (System.currentTimeMillis() - mPressedHoldTime > PRESSED_HOLD_UPDATE) {
					mPressedHoldTime = System.currentTimeMillis();
					if (mPressedListener != null) {
						mPressedListener.onPressed();
					}
				}
			} else if (getState() == State.PRESSED) {
				if (mPressedStartTime == 0) {
					mPressedStartTime = System.currentTimeMillis();
				} else if (System.currentTimeMillis() - mPressedStartTime > TRIGGER_PRESSED) {
					mIsPressedHoldState = true;
					mPressedHoldTime = System.currentTimeMillis();
					if (mPressedListener != null) {
						mPressedListener.onPressedTrigger();
					}
				}
			}
		}

		@Override
		public void dispose() {
			detachChildren();
			mText.dispose();
			super.dispose();
		}
	}

}
